﻿using System;
using System.Collections.Generic;
using System.Transactions;

namespace SalesSys.Comm.DAL
{
    /// <summary>
    /// 表示可以处理单元工作
    /// </summary>
    public interface IUnitOfWork
    {
        IUnitContext UnitContext { get; set; }

    }


    /// <summary>
    /// 单元工作上下文对象
    /// </summary>
    public interface IUnitContext : IDisposable
    {
        event Action Complete;
        event Action RollBack;
        /// <summary>
        /// 上下文共享数据
        /// </summary>
        IDictionary<string, object> ContextItem { get; }
        /// <summary>
        /// 发出单元工作完成信号
        /// </summary>
        void OnComplete();
        /// <summary>
        /// 发出回滚工作信号
        /// </summary>
        void OnRollBack();
    }
    public class DefUnitContext : IUnitContext
    {

        public event Action Complete;
        IDictionary<string, object> contextItem = new Dictionary<string, object>();

        public IDictionary<string, object> ContextItem
        {
            get { return contextItem; }
        }

        public void OnComplete()
        {
            if (Complete != null)
                Complete();
        }

        public event Action RollBack;
        public void OnRollBack()
        {
            if (RollBack != null)
                RollBack();
        }

        public void Dispose()
        {
        }
    }
    /// <summary>
    /// 使用TransactionScope实现的单元上下文
    /// </summary>
    [Obsolete("该类使用需谨慎，确认已完成数据库操作后应立即释放，不应再有业务")]
    public class TranScopeUnitContext : IUnitContext
    {
        readonly TransactionScope ts;
        public TranScopeUnitContext()
        {
            ts = new TransactionScope();
        }
        public event Action Complete;
        IDictionary<string, object> contextItem = new Dictionary<string, object>();

        public IDictionary<string, object> ContextItem
        {
            get { return contextItem; }
        }

        public void OnComplete()
        {
            if (Complete != null)
            {
                Complete();
                ts.Complete();
            }
        }

        public event Action RollBack;
        public void OnRollBack()
        {
            if (RollBack != null)
            {
                RollBack();
                ts.Dispose();
            }
        }
        public void Dispose()
        {
            ts.Dispose();
            ClearInvocation(Complete);
            ClearInvocation(RollBack);
        }

        private void ClearInvocation(MulticastDelegate dlg)
        {
            if (dlg==null)
            {
                return;
            }
            var inList = dlg.GetInvocationList();
            foreach (var item in inList)
            {
                Delegate.RemoveAll(Complete, item);
            }
        }
    }

}
